/**
 * @author		Ben Layet
 * @version 	0.1
 * @date		3 Sep 2008
 * @copyright 	� Canon Europa N. V. 2004
 */
package org.learnaholic.application;

import java.awt.Frame;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

import org.learnaholic.application.model.MemoryItems;
import org.learnaholic.application.model.MemoryItemsEvent;
import org.learnaholic.application.model.MemoryItemsImpl;
import org.learnaholic.application.model.MemoryListener;
import org.learnaholic.application.model.TestDialogDefinition;
import org.learnaholic.application.model.xml.ItemListParser;
import org.learnaholic.application.model.xml.ItemListWriter;
import org.learnaholic.application.model.xml.LearnaholicXmlException;
import org.learnaholic.application.test.TestImpl;
import org.learnaholic.application.ui.LearnaholicFrame;
import org.learnaholic.application.ui.LearnaholicUi;

/**
 * 
 */
public class LearnaholicImpl implements Learnaholic
{

	/** The singleton instance */
	private static LearnaholicImpl		instance;

	/** The application UI */
	private final LearnaholicUi			ui;
	/** The application model */
	private final MemoryItems			model;
	/** The application model */
	private TestDialogDefinition		testDialogDefinition;
	/** The model listener */
	private final MemoryEventHandler	memoryEventHandler	= new MemoryEventHandler();

	private final ItemListWriter		itemListWriter		= new ItemListWriter();
	private final ItemListParser		itemListParser		= new ItemListParser();

	/**
	 * Singleton getter.
	 * 
	 * @return the singleton instance.
	 */
	public static Learnaholic getInstance()
	{
		if (null == instance)
		{
			instance = new LearnaholicImpl();
		}
		return instance;
	}

	/**
	 * Sole private constructor.
	 */
	private LearnaholicImpl()
	{
		model = new MemoryItemsImpl();
		ui = new LearnaholicFrame();
		model.addMemoryListener(memoryEventHandler);
	}

	/**
	 * Releases the resource.
	 */
	public static void dispose()
	{
		instance = null;
	}

	/**
	 * @param list
	 */
	public void loadList(MemoryItems items)
	{
		model.putAll(items);
	}

	public MemoryItems getModel()
	{
		return model;
	}

	/**
	 * 
	 */
	public void start()
	{
		ui.start();
		InputStream listData = null;
		InputStream resultData = null;

		try
		{
			listData = new FileInputStream("res/ibis_french.xml");
			resultData = new FileInputStream("res/ibis_results.xml");
			loadXmlList(listData, resultData);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				listData.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			try
			{
				resultData.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		InputStream testDialogDefinitionData = null;

		try
		{
			testDialogDefinitionData = new FileInputStream("res/ibis french testdialog.xml");
			testDialogDefinition	= itemListParser.loadTestDialogDefinition(testDialogDefinitionData);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				testDialogDefinitionData.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
	}

	public void loadXmlList(InputStream xmlList, InputStream resultsXml)
	{

		try
		{
			loadList(itemListParser.loadXml(xmlList, resultsXml));
			// ui.displayItems();
		}
		catch (LearnaholicXmlException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 
	 */
	public void save()
	{
		try
		{
			FileWriter fileWriter = new FileWriter("res/results.xml");
			itemListWriter.write(fileWriter, model);
			fileWriter.flush();
			fileWriter.close();
			setBlurred(false);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 
	 */
	public void stop()
	{
		System.exit(0);
	}

	public void startTest(Set<String> items)
	{
		try
		{
			new TestImpl((Frame) ui, model, testDialogDefinition).startTest(model.getSubMap(items));
		}
		catch (LearnaholicException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * The model event handler.
	 */
	private class MemoryEventHandler implements MemoryListener
	{
		public void itemsAdded(MemoryItemsEvent evt)
		{
			ui.addItems(evt.getItems());
		}

		public void itemsRemoved(MemoryItemsEvent evt)
		{
			ui.removeItems(evt.getItems());
		}
	}

	/**
	 * 
	 */
	public void setBlurred(boolean blurred)
	{
		ui.setBlurred(blurred);
	}

}
